﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Sanford.Multimedia.Midi;

namespace Brio
{
    public partial class PlayerControl : UserControl
    {
        public PlayerControl()
        {
            InitializeComponent();

            
            sequence = new Sequence();
            sequencer = new Sequencer();
            timer = new Timer();
            
            // Set Properties and Attach Events for sequencer and sequence
            sequencer.Sequence = sequence;
            sequencer.ChannelMessagePlayed += new EventHandler<ChannelMessageEventArgs>(HandleChannelMessagePlayed);
            sequencer.Chased += new EventHandler<ChasedEventArgs>(HandleChased);
            sequencer.Stopped += new EventHandler<StoppedEventArgs>(HandleStopped);
            sequencer.PlayingCompleted += new EventHandler(HandlePlayingCompleted);
            sequence.LoadCompleted += HandleLoadCompleted;


            // Set Properties and Attach Events to timer
            timer.Interval = 50;
            timer.Tick += new EventHandler(timer_Tick);

            Playing = false;
            SetPlayerState(Playing);

        }


        public bool Playing;
        
        private OutputDevice outDevice;
        
        private Sequence sequence;
        private Sequencer sequencer;

        private Timer timer;

        public bool LoadFile(string fileName, OutputDevice device)
        {
            
            try
            {
                sequencer.Stop();
                Playing = false;

                // Display waiting cursor to user
                this.Cursor = Cursors.WaitCursor;
                sequence.LoadAsync(fileName);

                
                outDevice = device;
            }
            catch (Exception exception)
            {
                return false;
            }

            return true;
        }


        private void ControlsButton_Click(object sender, EventArgs e)
        {
            Playing = !Playing;
            SetPlayerState(Playing);
        }

        public void ResetPlayer()
        {
            Playing = false;
            SetPlayerState(Playing);
        }

        public void SetPlayerState(bool playing)
        {
            // Show Play State
            if (playing)
            {
                // If we're playing the image we should see is to pause the player
                ControlsButton.BackgroundImage = global::Brio.Properties.Resources.Pause;

                // Start MIDI
                try
                {
                    sequencer.Start();
                    sequencer.Position = PlaybackPositionControl.Value;
                    timer.Start();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                }

            }
            // Show Pause State
            else
            {
                // If we're pausing the image we should see it to start the player
                ControlsButton.BackgroundImage = global::Brio.Properties.Resources.Play;

                // Stop MIDI
                try
                {
                    sequencer.Stop();
                    timer.Stop();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                }
            }

        }

        private void PlayerControl_Load(object sender, EventArgs e)
        {
            
        }

        private void HandleLoadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            this.Cursor = Cursors.Arrow;

            ControlsButton.Enabled = true;

            
            if (e.Error == null)
            {
                PlaybackPositionControl.Value = 0;
                PlaybackPositionControl.Maximum = sequence.GetLength();
                PlaybackPositionControl.SmallChange = PlaybackPositionControl.Maximum / 100;
            }
            else
            {
                MessageBox.Show(e.Error.Message);
            }
        }

        // Sequencer Stop Event
        private void HandleStopped(object sender, StoppedEventArgs e)
        {
            // Tell Out Device to hush up!
            foreach (ChannelMessage message in e.Messages)
            {
                outDevice.Send(message);
            }
        }

        // Sequencer Chase Event
        private void HandleChased(object sender, ChasedEventArgs e)
        {
            foreach (ChannelMessage message in e.Messages)
            {
                outDevice.Send(message);
            }
        }

        // Sequencer Play Event
        private void HandleChannelMessagePlayed(object sender, ChannelMessageEventArgs e)
        {
            try
            {

                outDevice.Send(e.Message);
            }
            catch (Exception exception)
            {

            }
        }

        // Sequencer Finish Event
        private void HandlePlayingCompleted(object sender, EventArgs e)
        {
            timer.Stop();

            ResetPlayer();
        }

        // Timer Tick Event to handle Playback Position
        private void timer_Tick(object sender, EventArgs e)
        {
            if (Playing)
            {
                PlaybackPositionControl.Value = sequencer.Position > PlaybackPositionControl.Maximum ? PlaybackPositionControl.Maximum : sequencer.Position;
            }

        }        


    }
}
